#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include "fbtft.h"

#define DRVNAME		"fb_ili9488"

static int init_display(struct fbtft_par *par)
{
	par->fbtftops.reset(par);

	/* startup sequence for ER-TFT035-6 */
	write_reg(par, 0x01); /* software reset */

	gpiod_set_value(par->gpio.reset, 1);
	mdelay(5);
	gpiod_set_value(par->gpio.reset, 0);
	mdelay(20);
	gpiod_set_value(par->gpio.reset, 1);
	mdelay(150);

	write_reg(par, 0xE0, 0x00, 0x03, 0x09, 0x08, 0x16, 0x0A, 0x3F, 0x78, 0x4C, 0x09, 0x0A, 0x08, 0x16, 0x1A, 0x0F); 
	write_reg(par, 0xE1, 0x00, 0x16, 0x19, 0x03, 0x0F, 0x05, 0x32, 0x45, 0x46, 0x04, 0x0E, 0x0D, 0x35, 0x37, 0x0F);
	write_reg(par, 0xC0, 0x17, 0x15);
	write_reg(par, 0xC1, 0x41);
	write_reg(par, 0xC5, 0x00, 0x12, 0x80);
	write_reg(par, 0x36, 0x48);
	write_reg(par, 0x3A, 0x66);
	write_reg(par, 0xB0, 0x00);
	write_reg(par, 0xB1, 0xA0);
	write_reg(par, 0xB4, 0x02);
	write_reg(par, 0xB6, 0x02, 0x02, 0x3B);
	write_reg(par, 0xB7, 0xC6);
	write_reg(par, 0xF7, 0xA9, 0x51, 0x2C, 0x82);
	
	write_reg(par, 0x11); /* sleep out */
	mdelay(150);
	write_reg(par, 0x29); /* display on */
	mdelay(120);
	
	return 0;
}
	
static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
{
	/* Column address */
	write_reg(par, 0x2A, xs >> 8, xs & 0xFF, xe >> 8, xe & 0xFF);

	/* Row adress */
	write_reg(par, 0x2B, ys >> 8, ys & 0xFF, ye >> 8, ye & 0xFF);

	/* Memory write */
	write_reg(par, 0x2C);
}

/* 16bpp converted to 18bpp stored in 24-bit over 8-bit databus */
int write_vmem16_bus8(struct fbtft_par *par, size_t offset, size_t len)
{
	u16 *vmem16;
	u8 *txbuf = par->txbuf.buf;
	size_t remain;
	size_t to_copy;
	size_t tx_array_size;
	int i;
	int ret = 0;

	/* remaining number of pixels to send */
	remain = len / 2;
	vmem16 = (u16 *)(par->info->screen_buffer + offset);

	if ((int)(par->gpio.dc) != -1)
		gpiod_set_value(par->gpio.dc, 1);

	/* number of pixels that fits in the transmit buffer */
	tx_array_size = par->txbuf.len / 3;

	while (remain) {
		/* number of pixels to copy in one iteration of the loop */
		to_copy = min(tx_array_size, remain);
		dev_dbg(par->info->device, "    to_copy=%zu, remain=%zu\n",
						to_copy, remain - to_copy);

		for (i = 0; i < to_copy; i++) {
			u16 pixel = vmem16[i];
			u16 b = pixel & 0x1f;
			u16 g = (pixel & (0x3f << 5)) >> 5;
			u16 r = (pixel & (0x1f << 11)) >> 11;

			u8 r8 = (r & 0x1F) << 3;
			u8 g8 = (g & 0x3F) << 2;
			u8 b8 = (b & 0x1F) << 3;

			txbuf[i * 3 + 0] = r8;
			txbuf[i * 3 + 1] = g8;
			txbuf[i * 3 + 2] = b8;
		}

		vmem16 = vmem16 + to_copy;
		ret = par->fbtftops.write(par, par->txbuf.buf, to_copy * 3);
		if (ret < 0)
			return ret;
		remain -= to_copy;
	}

	return ret;
}
EXPORT_SYMBOL(write_vmem16_bus8);

static int set_var(struct fbtft_par *par)
{
	switch (par->info->var.rotate) {
	case 0:
		write_reg(par, 0x36, 0x80 | (par->bgr << 3));
		break;
	case 90:
		write_reg(par, 0x36, 0x20 | (par->bgr << 3));
		break;
	case 180:
		write_reg(par, 0x36, 0x40 | (par->bgr << 3));
		break;
	case 270:
		write_reg(par, 0x36, 0xE0 | (par->bgr << 3));
		break;
	default:
		break;
	}

	return 0;
}

static struct fbtft_display display = {
	.fbtftops = {
		.init_display = init_display,
		.set_addr_win = set_addr_win,
		.set_var = set_var,
		.write_vmem = write_vmem16_bus8,
	},
};
FBTFT_REGISTER_DRIVER(DRVNAME, "ilitek,ili9488", &display);

MODULE_ALIAS("spi:" DRVNAME);
MODULE_ALIAS("platform:" DRVNAME);
MODULE_ALIAS("spi:ili9488");
MODULE_ALIAS("platform:ili9488");

MODULE_DESCRIPTION("FB driver for the ILI9488 LCD Controller");
MODULE_AUTHOR("BIRD TECHSTEP");
MODULE_LICENSE("GPL");

/************************************************************
 设备树示例，基于全志H2+主控，Linux5.6.2内核，
 可以修改的有spi总线、reset-gpios、dc-gpios、rotate.
 
&spi1 {
        status = "okay";

        tft-lcd@0 {
                compatible = "ilitek,ili9488";
                reg = <0>;
                spi-max-frequency = <74999000>;

                reset-gpios = <&pio 0 3 GPIO_ACTIVE_HIGH>;
                dc-gpios = <&pio 0 7 GPIO_ACTIVE_HIGH>;
                status = "okay";

                rotate = <0>;
                fps = <60>;
                buswidth = <8>;
                regwidth = <8>;
                width = <320>;
                height = <480>;
                bpp = <16>;
        };

};

请将此驱动程序放在linux_kernel/driver/staging/fbtft/进行编译
***************************************************************/